//
//  JSFormView.swift
//  AmountBody
//
//  Created by Qiu Jishuai on 2018/1/30.
//

import UIKit
//freeze panes  冻结窗格功能
//排列模式
@objc protocol JSFormViewDelegate: class {
    
    func numberOfCells(in formView: JSFormView) -> Int

    /// 每个单元格内每段文字区域的设置
    @objc optional func formView(_ formView: JSFormView, insetsForCellAt index: Int) -> UIEdgeInsets

    /// 每个单元格内每段文字区域的设置
    func formView(_ formView: JSFormView, configForColumnAt index: Int) -> [JSFromCellItemConfig]

    /// 列数, 如果未实现, 默认为1
    @objc optional func numberOfColumns(in formView: JSFormView) -> Int

    /// 布局完成后调用
    @objc optional func layoutCompletion()

    /// 每列的宽度, 如果未实现该方法, 则按照数量等分宽度
    @objc optional func formView(_ formView: JSFormView, widthForColumnAt column: Int) -> CGFloat
}

extension NSTextAlignment {
    var asCAAlignment: String {
        switch self {
        case .center: return kCAAlignmentRight
        case .left: return kCAAlignmentLeft
        case .justified: return kCAAlignmentJustified
        case .natural: return kCAAlignmentNatural
        case .right: return kCAAlignmentRight
        }
    }
}

//表格
class JSFormView: UIView {

    func cellForIndex(_ index: Int) -> JSFromCell? {
        guard cells.count - 1 > index else { return nil }
        return cells[index]
    }

    let contentView: UIView = {
        let container = UIView()
        container.backgroundColor = UIColor.themebackgroundColor
        return container
    }()

    var cells: [JSFromCell] = []

    var defaultFont: UIFont = .systemFont(ofSize: 10) {
        didSet {
            cells.forEach { (cell) in
                cell.defaultFont = defaultFont
            }
        }
    }

    var defaultTextColor: UIColor = .themeDarkGrayColor {
        didSet {
            cells.forEach { (cell) in
                cell.defaultTextColor = defaultTextColor
            }
        }
    }

    var contentInsets: UIEdgeInsets = .zero {
        didSet {
            layoutSubviews()
        }
    }

    var numberOfColumns: Int {
        return delegate?.numberOfColumns?(in: self) ?? 1
    }

    private var columnHeights: [CGFloat] = []
    private var columnFrame: [CGRect] = []

    weak var delegate: JSFormViewDelegate?

    override var intrinsicContentSize: CGSize {
        return CGSize(width: self.width, height: columnHeights.max() ?? 0)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let x = contentInsets.left
        let y = contentInsets.top
        let width = frame.width - (contentInsets.left + contentInsets.right)
        let height = frame.height - (contentInsets.top + contentInsets.bottom)
        contentView.frame = CGRect(x: x, y: y, width: width, height: height)
        redrawGirds()
    }

    func redrawGirds() {
        //重新排列
        let targetCellsCount = delegate?.numberOfCells(in: self) ?? 0

        //初始化尺寸
        columnHeights = (0..<numberOfColumns).map{ _ in CGFloat(0) }

        columnFrame = []
        for i in 0..<numberOfColumns {
            let x: CGFloat
            if i == 0 {
                x = 0
            } else {
                x = columnFrame[i - 1].maxX
            }
            let width = columnWidth(for: i)
            let frame = CGRect(x: x, y: 0, width: width, height: height)
            columnFrame.append(frame)
        }

        while cells.count > targetCellsCount {
            cells.removeLast().removeFromSuperlayer()
        }

        while cells.count < targetCellsCount {
            let cell = JSFromCell()
            cell.defaultFont = defaultFont
            cell.defaultTextColor = defaultTextColor
            //            cell.shouldRasterize = true
            //            cell.contentsScale = UIScreen.main.scale
            cells.append(cell)
            contentView.layer.addSublayer(cell)
        }
        calculteSize()
    }
    //    var cachePool: [CATextLayer] = []
}

//MARK: - Private method
private extension JSFormView {
    func setup() {
        addSubview(contentView)
    }

    //高度最小的
    var minHeight: CGFloat {
        return columnHeights.min() ?? columnHeights.first ?? 0
    }

    //高度最小的一列
    var minCol: Int {
        return columnHeights.index(where: { $0 == minHeight }) ?? 0
    }

    //计算总体的布局尺寸
    func calculteSize() {
        print("calculteSize")
        CATransaction.setDisableActions(true)

        for (index, cell) in self.cells.enumerated() {

            let targetColumn = self.columnFrame[self.minCol]
            let cellInsets = delegate?.formView?(self, insetsForCellAt: index) ?? .zero

            //单元格的宽度等于列宽减去inset
            let cellWidth = targetColumn.width - cellInsets.left - cellInsets.right

            guard let configs = self.delegate?.formView(self, configForColumnAt: index) else {
                continue
            }
            cell.width = cellWidth
            cell.configs = configs

            let x = targetColumn.minX + cellInsets.left
            let y = self.minHeight + cellInsets.top

            //累积到最短的列高度上
            self.columnHeights[self.minCol] = y + cell.cellHeight + cellInsets.bottom
            cell.frame = CGRect(x: x, y: y, width: cellWidth, height: cell.cellHeight)
            cell.configs = configs
        }
        CATransaction.setDisableActions(false)
        //重新布局
        invalidateIntrinsicContentSize()
        var superview = self.superview
        superview?.setNeedsLayout()
        superview?.layoutIfNeeded()
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            while superview != nil {
                if let tableView = superview as? UITableView {
                    tableView.beginUpdates()
                    tableView.endUpdates()
                }
                superview = superview?.superview
            }
        }
        self.delegate?.layoutCompletion?()
    }

    func columnWidth(for column: Int) -> CGFloat {
        return delegate?.formView?(self, widthForColumnAt: column) ?? ((frame.width - (contentInsets.left + contentInsets.right)) / CGFloat(numberOfColumns))
    }
}
